from typing import Dict, List, Any, Optional
from dataclasses import dataclass
import networkx as nx
import pandas as pd
import numpy as np
from pathlib import Path
import json
import logging
from datetime import datetime
from knowledge_graph import JobKnowledgeGraph
from salary_predictor import SalaryPredictor

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger("CareerPlanner")

@dataclass
class CareerPath:
    """职业发展路径数据类"""
    path_id: str
    target_job: str
    current_to_target: List[str]  # 职位发展序列
    required_skills: Dict[str, List[str]]  # 各阶段需要掌握的技能
    time_estimates: Dict[str, int]  # 各阶段预计时间(月)
    salary_projection: Dict[str, float]  # 各阶段薪资预测
    learning_resources: Dict[str, List[str]]  # 学习资源推荐

class CareerPlanner:
    """职业发展路径规划器"""
    def __init__(self, kg_client: JobKnowledgeGraph):
        self.kg = kg_client
        self.salary_predictor = SalaryPredictor()
        self.career_graph = self._build_career_graph()
        self.resource_dir = Path("b/data/learning_resources")
        self._init_resources()
        
    def _build_career_graph(self) -> nx.DiGraph:
        """构建职业发展关系图"""
        G = nx.DiGraph()
        
        # 从知识图谱获取职业发展路径
        career_paths = self.kg.get_career_paths()
        
        # 添加节点和边
        for path in career_paths:
            source = path["from"]
            target = path["to"]
            weight = path.get("weight", 1)
            G.add_edge(source, target, weight=weight)
            
        logger.info(f"职业发展图构建完成，包含 {len(G.nodes)} 个职位节点")
        return G
    
    def _init_resources(self):
        """初始化学习资源目录"""
        self.resource_dir.mkdir(parents=True, exist_ok=True)
        
        # 创建示例资源文件 (如果不存在)
        sample_file = self.resource_dir / "programming_resources.json"
        if not sample_file.exists():
            sample_resources = {
                "Python": [
                    "《Python编程：从入门到实践》",
                    "Python官方文档(https://docs.python.org/)",
                    "LeetCode Python练习题"
                ],
                "机器学习": [
                    "Coursera机器学习课程(Andrew Ng)",
                    "《机器学习实战》",
                    "Kaggle竞赛"
                ]
            }
            with open(sample_file, "w", encoding="utf-8") as f:
                json.dump(sample_resources, f, ensure_ascii=False, indent=2)
            logger.info("已创建示例学习资源文件")
    
    def plan_career_paths(self, current_job: str, current_skills: List[str],
                         target_industry: Optional[str] = None,
                         max_paths: int = 3) -> List[CareerPath]:
        """规划职业发展路径"""
        # 获取所有可能的目标职位
        if target_industry:
            target_jobs = self._get_industry_jobs(target_industry)
        else:
            target_jobs = list(self.career_graph.nodes)
            
        # 寻找从当前职位到目标职位的路径
        all_paths = []
        for target in target_jobs:
            try:
                paths = list(nx.all_shortest_paths(
                    self.career_graph,
                    source=current_job,
                    target=target
                ))
                all_paths.extend(paths[:max_paths])
            except nx.NetworkXNoPath:
                continue
                
        # 转换为CareerPath对象
        career_paths = []
        for i, path in enumerate(all_paths[:max_paths], 1):
            career_path = self._build_career_path(
                path_id=f"path_{i}",
                path=path,
                current_skills=current_skills
            )
            if career_path:
                career_paths.append(career_path)
        
        # 按薪资增长潜力排序
        career_paths.sort(
            key=lambda x: list(x.salary_projection.values())[-1],
            reverse=True
        )
        
        logger.info(f"为 {current_job} 规划了 {len(career_paths)} 条发展路径")
        return career_paths
    
    def _build_career_path(self, path_id: str, path: List[str],
                         current_skills: List[str]) -> Optional[CareerPath]:
        """构建完整的职业发展路径对象"""
        try:
            target_job = path[-1]
            required_skills = {}
            time_estimates = {}
            salary_projection = {}
            learning_resources = {}
            
            # 分析路径上的每个职位
            for i, job in enumerate(path):
                # 获取职位所需技能
                job_skills = self.kg.get_job_skills(job)
                required_skills[job] = [
                    skill for skill in job_skills 
                    if skill not in current_skills
                ]
                
                # 估算时间 (基于技能差距)
                time_estimates[job] = min(
                    24, max(6, len(required_skills[job]) * 2)
                )
                
                # 预测薪资
                salary_data = {
                    "years_experience": i * 2,
                    "education_level": 4,  # 假设本科
                    "skill_count": len(job_skills),
                    "industry": self.kg.get_job_industry(job),
                    "location_tier": 1  # 一线城市
                }
                salary_pred = self.salary_predictor.predict_salary(salary_data)
                salary_projection[job] = salary_pred["predicted_salary"]
                
                # 推荐学习资源
                learning_resources[job] = []
                for skill in required_skills[job]:
                    resources = self._get_learning_resources(skill)
                    if resources:
                        learning_resources[job].extend(resources[:2])  # 每个技能最多2个资源
            
            return CareerPath(
                path_id=path_id,
                target_job=target_job,
                current_to_target=path,
                required_skills=required_skills,
                time_estimates=time_estimates,
                salary_projection=salary_projection,
                learning_resources=learning_resources
            )
            
        except Exception as e:
            logger.error(f"构建职业路径失败: {str(e)}", exc_info=True)
            return None
    
    def _get_industry_jobs(self, industry: str) -> List[str]:
        """获取特定行业的所有职位"""
        return self.kg.get_jobs_by_industry(industry)
    
    def _get_learning_resources(self, skill: str) -> List[str]:
        """获取技能学习资源"""
        resources = []
        
        # 从资源文件中查找
        for res_file in self.resource_dir.glob("*.json"):
            with open(res_file, "r", encoding="utf-8") as f:
                res_data = json.load(f)
                if skill in res_data:
                    resources.extend(res_data[skill])
        
        return resources[:5]  # 每个技能最多返回5个资源
    
    def generate_development_plan(self, user_data: Dict[str, Any]) -> Dict[str, Any]:
        """生成职业发展计划报告"""
        # 获取发展路径
        paths = self.plan_career_paths(
            current_job=user_data["current_job"],
            current_skills=user_data["skills"],
            target_industry=user_data.get("target_industry"),
            max_paths=3
        )
        
        if not paths:
            return {"error": "未找到合适的发展路径"}
        
        # 构建报告
        report = {
            "user_info": {
                "current_job": user_data["current_job"],
                "skill_count": len(user_data["skills"]),
                "target_industry": user_data.get("target_industry")
            },
            "generated_at": datetime.now().isoformat(),
            "recommended_paths": []
        }
        
        for path in paths:
            # 计算路径总时长
            total_months = sum(path.time_estimates.values())
            
            # 构建里程碑
            milestones = []
            cumulative_months = 0
            for i, job in enumerate(path.current_to_target):
                cumulative_months += path.time_estimates[job]
                milestones.append({
                    "sequence": i + 1,
                    "target_job": job,
                    "time_estimate": path.time_estimates[job],
                    "cumulative_time": cumulative_months,
                    "salary_projection": path.salary_projection[job],
                    "key_skills_to_learn": path.required_skills[job],
                    "learning_resources": path.learning_resources[job]
                })
            
            report["recommended_paths"].append({
                "path_id": path.path_id,
                "target_job": path.target_job,
                "total_duration_months": total_months,
                "expected_salary_growth": (
                    path.salary_projection[path.target_job] - 
                    path.salary_projection[path.current_to_target[0]]
                ),
                "milestones": milestones
            })
        
        # 保存报告
        report_file = Path(f"b/data/career_reports/{user_data['user_id']}_report.json")
        report_file.parent.mkdir(exist_ok=True)
        with open(report_file, "w", encoding="utf-8") as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
        
        logger.info(f"职业发展报告已保存到 {report_file}")
        return report

if __name__ == "__main__":
    # 示例使用
    kg = JobKnowledgeGraph()
    planner = CareerPlanner(kg)
    
    # 示例用户数据
    user_data = {
        "user_id": "user123",
        "current_job": "初级Python开发工程师",
        "skills": ["Python", "SQL"],
        "target_industry": "IT"
    }
    
    # 生成职业发展路径
    print("\n生成职业发展路径...")
    paths = planner.plan_career_paths(
        current_job=user_data["current_job"],
        current_skills=user_data["skills"],
        target_industry=user_data["target_industry"]
    )
    
    for path in paths:
        print(f"\n路径ID: {path.path_id}")
        print(f"目标职位: {path.target_job}")
        print("发展序列:", " -> ".join(path.current_to_target))
        print("预计薪资增长:", 
              f"{path.salary_projection[path.current_to_target[0]]:,.2f} -> "
              f"{path.salary_projection[path.target_job]:,.2f} CNY")
    
    # 生成完整发展计划
    print("\n生成职业发展计划报告...")
    report = planner.generate_development_plan(user_data)
    print(f"已生成 {len(report['recommended_paths'])} 条推荐路径")